import ctypes
import sys
import win32gui
import os
from helper import *

# 在导入soui4py之前设置DLL路径
souiRootDir = os.path.dirname(os.path.abspath(__file__))
result = setup_soui_dll_path(souiRootDir)
if not result:
    print("Failed to setup SOUI DLL path")

try:
    from soui4py import *
    print("Successfully imported soui4py")
except ImportError as e:
    print(f"Failed to import soui4py: {e}")
    import traceback
    traceback.print_exc()

from events import *
from message import *

class DlgTest(SHostDialog):
    events = EventHandler()
    messages = MessageHandler()
    def __init__(self):
        super().__init__(soui_factory.CreateHostDialog('LAYOUT:DLG_TEST'))
        self.SetEventHandler(self.events)
        self.SetMsgHandler(self.messages)

    @events.EVENT_ID_COMMAND(DialogID.IDCANCEL)
    def OnOK(self):
        self.EndDialog(DialogID.IDOK)

    @messages.MSG_WM_INITDIALOG
    def OnInitDialog(self, hWnd, lParam):
        print('init dialog', hWnd)
        btn_close = self.FindChildByName('btn_close')
        slot = soui_factory.CreateFuncSlot(self.OnBtnClose)
        btn_close.SubscribeEvent(Event.EVT_CMD, slot)
        slot.Release()
    
    def OnBtnClose(self, evt_args):
        self.EndDialog(DialogID.IDCANCEL)
        return True

class CAdapterTest(SLvAdapter):
    def __init__(self):
        super().__init__()
    def getCount(self):
        return 100
    
    def getView(self, position, pItem, xmlTemplate):
        if pItem.GetChildrenCount() == 0:
            pItem.InitFromXml(xmlTemplate)
        txt_test = pItem.FindChildByName('txt_test')
        txt_test.SetWindowText('item %s' % (position))
        
        btn_test = pItem.FindChildByName('btn_test')
        btn_test.SetUserData(position)
        slot = soui_factory.CreateFuncSlot(self.OnBtnTest)
        btn_test.SubscribeEvent(Event.EVT_CMD, slot)
        slot.Release()

    def OnBtnTest(self, evt: SEvtArgs):
        sender = SWindow(evt.Sender())
        evt2 = EventCmd.from_address(evt.Data())
        pos = sender.GetUserData()
        print('btn', pos)
        return True

class MainDlg(SHostWnd):
    events = EventHandler()
    messages = MessageHandler()
    def __init__(self):
        super().__init__(soui_factory.CreateHostWnd('LAYOUT:XML_MAINWND'))
        self.SetEventHandler(self.events)
        self.SetMsgHandler(self.messages)

    @messages.MSG_WM_INITDIALOG
    def OnInitDialog(self, hWnd, lParam):
        print('init', hWnd)
        self._lv_test = self.FindChildByName2('lv_test', SListView)
        if self._lv_test:
            self._adapter_test = CAdapterTest()
            self._lv_test.SetAdapter(self._adapter_test)
            self._adapter_test.Release()
        
    @events.EVENT_NAME_COMMAND('btn_flash')
    def OnBtnFlash(self):
        win32gui.FlashWindow(self._hWnd, 1)
        
    @events.EVENT_NAME_HANDLER('btn_menu', Event.EVT_CMD)
    def OnBtnMenu(self, evt: SEvtArgs):
        sender = SWindow(evt.Sender())
        rect_sender = sender.GetWindowRect()
        rect_btn = self.ClientToScreen2(rect_sender)
        menu = soui_factory.CreateMenu()
        menu.LoadMenu('SMENU:menu_test')
        r = menu.TrackPopupMenu(0x0100, rect_btn['left'], rect_btn['bottom'], self._hWnd)
        if r == 6:
            self.DestroyWindow()
        menu.Release()
        
    @events.EVENT_NAME_HANDLER('btn_menuex', Event.EVT_CMD)
    def OnBtnMenuex(self, evt: SEvtArgs):
        sender = SWindow(evt.Sender())
        rect_sender = sender.GetWindowRect()
        rect_btn = self.ClientToScreen2(rect_sender)
        menu = soui_factory.CreateMenuEx()
        menu.LoadMenu('SMENU:menuex_test')
        r = menu.TrackPopupMenu(0x0100, rect_btn['left'], rect_btn['bottom'], self._hWnd)
        if r == 6:
            self.DestroyWindow()
        menu.Release()

    @events.EVENT_NAME_HANDLER('btn_dialog', Event.EVT_CMD)
    def OnBtnDialog(self, evt: SEvtArgs):
        dlg = DlgTest()
        dlg.DoModal()
        dlg.Release()
        
    @events.EVENT_NAME_COMMAND('btn_msgbox')
    def OnBtnMsgBox(self):
        SMessageBox(self._hWnd, 'Msgbox', 'msgbox', MB.MB_ICONINFORMATION)


def main():
    global soui_factory, app, decoder_factory, render_factory

    soui_factory = SouiFactory(sys.dllhandle)
    if soui_factory.ptr() == None:
        print('创建SouiFactory失败!')
        return
    SOUI.SOUI_FACTORY = soui_factory

    decoder_factory = soui_factory.CreateImgDecoder_Stb()
    if decoder_factory.ptr() == None:
        print('创建DecoderFactory失败!')
        return
    SOUI.DECODER_FACTORY = decoder_factory

    render_factory = soui_factory.CreateRender_GDI()
    if render_factory.ptr() == None:
        print('创建RenderFactory失败!')
        return
    SOUI.RENDER_FACTORY = render_factory

    render_factory.SetImgDecoderFactory(decoder_factory)

    app = soui_factory.CreateApp(render_factory)
    if app.ptr() == None:
        print('创建App失败!')
        return
    SOUI.APP = app

    dll = ctypes.CDLL('soui-sys-resource.dll')
    res_provider_system = soui_factory.CreateResProvider(RES_PE)
    if not res_provider_system.Init(dll._handle):
        print('加载系统资源失败!')
        return
    app.LoadSystemNamedResource(res_provider_system)
    res_provider_system.Release()

    res_provider_user = soui_factory.CreateResProvider(RES_FILE)
    # 使用UTF-8地址而不是直接传递字符串
    addr, buffer = get_string_utf8_address('uires')
    if not res_provider_user.Init(addr):
        print('加载用户资源失败!')
        return
    res_provider_mgr = app.GetResProviderMgr()
    res_provider_mgr.AddResProvider(res_provider_user, 'uidef:xml_init')
    # 保持对buffer的引用直到Init调用完成
    del buffer  # 现在可以安全删除引用

    dlg = MainDlg()
    
    dlg.Create()
    dlg.SendMessage(0x0110)
    dlg.ShowWindow(1)
    
    app.EnableNotifyCenter(True)
    SOUI.NOTIFY_CENTER = app.GetInnerSingleton(SingletonType.SINGLETON_NOTIFYCENTER)
    
    nRet = app.Run(dlg.GetHwnd())
    
    app.EnableNotifyCenter(False)
    
    dlg.Release()
    app.Release()
    soui_factory.Release()
    
    print('nRet:', nRet)

if __name__ == '__main__':
    main()
